package com.tomtop.core.datasource.core;

import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.logging.log4j.Log4jImpl;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.ClassUtils;

import com.github.pagehelper.PageHelper;
import com.tomtop.core._enum.CustomStatus;
import com.tomtop.core.datasource.config.DruidConfig;
import com.tomtop.core.datasource.config.DruidConfig.DruidNode;
import com.tomtop.core.datasource.config.DruidProperties;
import com.tomtop.core.exception.CustomException;

import tk.mybatis.spring.mapper.MapperScannerConfigurer;

public class AbstractDataBase {

	public static enum Mapper{
		 DEFAULT("tk.mybatis.mapper.common.Mapper"),
		 MYSQL("tk.mybatis.mapper.common.MySqlMapper,"+DEFAULT.mapper),
		 MSSQL("tk.mybatis.mapper.common.SqlServerMapper,"+DEFAULT.mapper);
		String mapper;
		private Mapper(String mapper) {
			this.mapper=mapper;
		}
		@Override
		public String toString() {
			return mapper;
		}
	}
	public static enum Order{
		 AFTER("after"),
		 BEFORE("before");
		 String order;
		 private Order(String order) {
			this.order=order;
		}
		@Override
		public String toString() {
			return order;
		}
	}
	public static class MybatisConfig{
			
		private Mapper mapper=Mapper.DEFAULT;
		private Order order=Order.BEFORE;
		private String basepackage;
		private String mapperpackage;

		public MybatisConfig() {
		}
		public MybatisConfig(String basepackage,String mapperpackage) {
			this.basepackage=basepackage;
			this.mapperpackage=mapperpackage;
		}
		public MybatisConfig(String basepackage,String mapperpackage,Mapper mapper,Order order) {
			this(basepackage, mapperpackage);
			this.mapper=mapper;
			this.order=order;
		}
		public static MybatisConfig now(String basepackage,String mapperpackage) {
			return new MybatisConfig(basepackage, mapperpackage);
		}
		public static MybatisConfig now(String basepackage,String mapperpackage,Mapper mapper,Order order) {
			return new MybatisConfig(basepackage, mapperpackage, mapper, order);
		}
		
		public Mapper getMapper() {
			return mapper;
		}
		public void setMapper(Mapper mapper) {
			this.mapper = mapper;
		}
		public Order getOrder() {
			return order;
		}
		public void setOrder(Order order) {
			this.order = order;
		}
		public String getBasepackage() {
			return basepackage;
		}
		public void setBasepackage(String basepackage) {
			this.basepackage = basepackage;
		}
		public String getMapperpackage() {
			return mapperpackage;
		}
		public void setMapperpackage(String mapperpackage) {
			this.mapperpackage = mapperpackage;
		}
	}
	public final static  DynamicDataSource createDataSource(DruidConfig druidConfig,String dataSourceName) {
		if(druidConfig==null||druidConfig.getDruid()==null){
			throw new CustomException(CustomStatus.FAIL,String.format("DynamicDataSource 未初始化 ,dataSourceName=%s,失败原因: 配置参数为空,你的配置可能存在问题!", dataSourceName+""));
		}
		DruidNode druidNode=druidConfig.getDruid().get(dataSourceName);
		DruidProperties defaultDruidProperties=druidConfig.getDefaultConfig();
		try {
			return DynamicDataSource.create(druidNode, defaultDruidProperties);
		} catch (SQLException e) {
			throw new CustomException(CustomStatus.FAIL,String.format("DynamicDataSource 初始化失败 ,dataSourceName=%s,失败原因:ErrorCode=%s,Message=%s,SQLState=%s",dataSourceName+"",e.getErrorCode()+"",e.getMessage()+"",e.getSQLState()+""));
		}
	}
	
	public final static  DataSourceTransactionManager createTransactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); }
	public final static  JdbcTemplate createJdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); }
	public final static SqlSessionFactory createSqlSessionFactory(DataSource datasource,MybatisConfig mc) {
		String mapperPackage=mc==null?null:mc.getMapperpackage();
		org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration();
		configuration.setCacheEnabled(true);
		configuration.setLazyLoadingEnabled(true);
		configuration.setAggressiveLazyLoading(true);
		configuration.setDefaultExecutorType( ExecutorType.SIMPLE);
		configuration.setLogImpl(Log4jImpl.class);
		SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
		sqlSessionFactory.setConfiguration(configuration);
		sqlSessionFactory.setFailFast(true);
		sqlSessionFactory.setDataSource(datasource);
		PageHelper pageHelper=new PageHelper();
		Properties p=new Properties();
		pageHelper.setProperties(p);
		sqlSessionFactory.setPlugins( new Interceptor[]{pageHelper});
		String mapperPackagePath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX+ ClassUtils.convertClassNameToResourcePath(new StandardEnvironment().resolveRequiredPlaceholders(mapperPackage)) + "/*.xml";
		try {
			sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperPackagePath));
			return sqlSessionFactory.getObject();
		} catch (Exception e) {
			throw new CustomException(CustomStatus.FAIL,e,String.format("SqlSessionFactory 初始化失败  mapperPackage=%s",mapperPackage+""));
		}
	}
	public final static MapperScannerConfigurer createScannerConfigurer( String sqlsessionfactorybeanname,MybatisConfig mc){
		String basepackage = null;
		Mapper mappers = null;
		Order order = null;
		if(mc!=null){
			basepackage = mc.getBasepackage();
			mappers = mc.getMapper();
			order = mc.getOrder();
		}
		MapperScannerConfigurer scannerConfigurer=new MapperScannerConfigurer();
		Properties properties=new Properties();
		properties.setProperty("notEmpty", "true");
		properties.setProperty("ORDER",  order!=null ?order.order:Order.BEFORE.order);
		properties.setProperty("mappers",mappers!=null?mappers.mapper: Mapper.DEFAULT.mapper);
		scannerConfigurer.setProperties(properties);
		scannerConfigurer.setSqlSessionFactoryBeanName(sqlsessionfactorybeanname);
		scannerConfigurer.setBasePackage(basepackage);
		return scannerConfigurer;
	}
}
